package com.sunda.spmswms.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sunda.spmscommon.Constans;
import com.sunda.spmscommon.ResponseResult;
import com.sunda.spmswms.entity.SapDeliveryNote;
import com.sunda.spmswms.entity.SapDeliveryNoteDtl;
import com.sunda.spmswms.entity.WhsStorageInventory;
import com.sunda.spmswms.mapper.SapDeliveryNoteDtlMapper;
import com.sunda.spmswms.mapper.SapDeliveryNoteMapper;
import com.sunda.spmswms.mapper.WhsStorageInventoryMapper;
import com.sunda.spmswms.service.ISapDeliveryNoteWithdrawMService;
import com.sunda.spmswms.service.IWhsOperateLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.List;

@Service
public class ISapDeliveryNoteWithdrawMServiceImpl extends ServiceImpl<SapDeliveryNoteMapper, SapDeliveryNote> implements ISapDeliveryNoteWithdrawMService {

    @Autowired
    WhsStorageInventoryMapper whsStorageInventoryMapper;
    @Autowired
    WhsStorageInventoryServiceImpl whsStorageInventoryService;
    @Autowired
    SapDeliveryNoteMapper sapDeliveryNoteMapper;
    @Autowired
    SapDeliveryNoteDtlMapper sapDeliveryNoteDtlMapper;
    @Autowired
    WithdrawTaskServiceImpl withdrawTaskService;
    @Autowired
    IWhsOperateLogService iWhsOperateLogService;

    /**
     * 检查是否可以冲销
     */
    @Override
    public ResponseResult isWithdrawableM(String deliveryNoteSap, String userId, String createDate) {
        SapDeliveryNote sapDeliveryNote = getSapDeliveryNote(deliveryNoteSap);
        List<SapDeliveryNoteDtl> sapDeliveryNoteDtls = sapDeliveryNoteDtlMapper.selectList(new QueryWrapper<SapDeliveryNoteDtl>().eq("DELIVERY_NOTE_SAP", deliveryNoteSap));
        if (null == sapDeliveryNote || null == sapDeliveryNoteDtls || sapDeliveryNoteDtls.size() <= 0) {
            // 无效的 sapDN号
            return ResponseResult.error("deliveryNoteSap: " + deliveryNoteSap + " is not validate, please double check");
        }
        String packageNote = sapDeliveryNote.getPackageNote();
        if (StringUtils.isNotEmpty(packageNote)) {
            // 非贸易货
            return ResponseResult.error("Only Trade goods allowed");
        }
        SapDeliveryNoteDtl sapDeliveryNoteDtl = sapDeliveryNoteDtls.get(0);
        String werks = sapDeliveryNoteDtl.getWerks();
        String whsLocationCode = sapDeliveryNoteDtl.getWhsLocationCode();
        String spmsStatus = sapDeliveryNote.getSpmsStatus();
        spmsStatus = StringUtils.isEmpty(spmsStatus) ? "0" : spmsStatus;

        /*
         * 货收货路径
         * null/0(待到货） --> 3 确认到货 --> 6 待上传SAP --> 7 上传SAP失败 --> 8 收货完成 -->11 关闭---> 0 已冲销
         * */

        switch (spmsStatus) {
            case "0":
                //  还没有开始的任务
                return ResponseResult.error("The given deliveryNoteSap:" + deliveryNoteSap + " not start yet");
            case "3":
            case "6":
            case "7":
            case "8":
            case "11":
                return checkStorageInventory(werks, whsLocationCode, sapDeliveryNoteDtls)
                        .add("spmsStatus", spmsStatus)
                        .add("sapVoucherNumber", sapDeliveryNote.getSapVoucherNumber())
                        .add("sapVoucherYear", sapDeliveryNote.getSapVoucherYear());
            default:
                return ResponseResult.error("SpmsStatus incorrect for sapDeliveryNote: " + deliveryNoteSap);
        }
    }

    /**
     * 执行库内数据冲销
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult withdrawSapDeliveryNote(String deliveryNoteSap, String userId, String createDate, String newSapVoucherNumber, String mobileType) {
        try {
            SapDeliveryNote sapDeliveryNote = getSapDeliveryNote(deliveryNoteSap);
            List<SapDeliveryNoteDtl> sapDeliveryNoteDtls = sapDeliveryNoteDtlMapper.selectList(new QueryWrapper<SapDeliveryNoteDtl>().eq("DELIVERY_NOTE_SAP", deliveryNoteSap));
            if (null == sapDeliveryNote || null == sapDeliveryNoteDtls || sapDeliveryNoteDtls.size() <= 0) {
                // 无效的 sapDN号
                throw new Exception("deliveryNoteSap: " + deliveryNoteSap + " is not validate, please double check");
            }
            String packageNote = sapDeliveryNote.getPackageNote();
            if (StringUtils.isNotEmpty(packageNote)) {
                // 非贸易货
                throw new Exception("Only Trade goods allowed");
            }
            SapDeliveryNoteDtl sapDeliveryNoteDtl = sapDeliveryNoteDtls.get(0);
            String werks = sapDeliveryNoteDtl.getWerks();
            String whsLocationCode = sapDeliveryNoteDtl.getWhsLocationCode();
            String spmsStatus = sapDeliveryNote.getSpmsStatus();
            spmsStatus = StringUtils.isEmpty(spmsStatus) ? "0" : spmsStatus;

            /*
             * 贸易货收货路径
             * null/0(待到货） --> 3 确认到货 --> 6 待上传SAP --> 7 上传SAP失败 --> 8 收货完成 -->11--->关闭---> 0 已冲销
             * */

            switch (spmsStatus) {
                case "3":
                case "6":
                case "7":
                case "8":
                case "11":
                    ResponseResult resetDtlRes = resetSapDeliveryNoteDtl(sapDeliveryNoteDtls, userId,werks,whsLocationCode);
                    if (resetDtlRes.getCode() != 200) {
                        // 更新行项目失败
                        throw new Exception(resetDtlRes.getMsg());
                    }
                    // 完成更新SapDN，返回
                    ResponseResult resetSapDNRes = resetSapDeliveryNote(deliveryNoteSap);
                    if (resetSapDNRes.getCode() != 200) {
                        // 冲销失败
                        throw new Exception(resetSapDNRes.getMsg());
                    }
                    return ResponseResult.success();
                default:
                    throw new Exception("SpmsStatus incorrect for sapDeliveryNote: " + deliveryNoteSap);
            }
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ResponseResult.error(e.getMessage());
        }

    }

    /* 根据deliveryNoteSap获取入库任务，取得入库任备状态 */
    @Override
    public SapDeliveryNote getSapDeliveryNote(String deliveryNoteSap) {
        return sapDeliveryNoteMapper.selectOne(new QueryWrapper<SapDeliveryNote>().eq("DELIVERY_NOTE_SAP", deliveryNoteSap));
    }

    /* 检查储位库存*/
    @Override
    public ResponseResult checkStorageInventory(String werks, String whsLocationCode, List<SapDeliveryNoteDtl> sapDeliveryNoteDtls) {
        try {
            for (int i = 0; i < sapDeliveryNoteDtls.size(); i++) {
                SapDeliveryNoteDtl sapDeliveryNoteDtl = sapDeliveryNoteDtls.get(i);
                String tempStorage = sapDeliveryNoteDtl.getTempStorage();
                double receivedQty = sapDeliveryNoteDtl.getReceivedQty() == null || "".equals(sapDeliveryNoteDtl.getReceivedQty().toString())
                        ? 0 : sapDeliveryNoteDtl.getReceivedQty();
                /** 只有实收数量大于 0 的行才需要校验库存是否足够 */
                if (receivedQty > 0){
                    if (StringUtils.isEmpty(tempStorage)) {
                        return ResponseResult.error("Can not find storage Info for materialNo: " + sapDeliveryNoteDtl.getMaterialNo());
                    }
                    JSONArray storageList = JSONArray.parseArray(sapDeliveryNoteDtl.getTempStorage());
                    if (null == storageList || storageList.size() <= 0) {
                        return ResponseResult.error("Can not find storage Info for materialNo: " + sapDeliveryNoteDtl.getMaterialNo());
                    }
                    for (int k = 0; k < storageList.size(); k++) {
                        JSONObject storageObj = storageList.getJSONObject(k);
                        String storageUuid = storageObj.getString("storageUuid");
                        int qty = storageObj.containsKey("qty") ? storageObj.getInteger("qty") : 0;
                        if (StringUtils.isEmpty(storageUuid) || qty <= 0) {
                            return ResponseResult.error("Can not find storage Info for materialNo: " + sapDeliveryNoteDtl.getMaterialNo());
                        }
                        WhsStorageInventory whsStorageInventory = whsStorageInventoryMapper
                                .selectOne(new QueryWrapper<WhsStorageInventory>()
                                        .eq("UUID", storageUuid)
                                        .eq("MATERIAL_NO", sapDeliveryNoteDtl.getMaterialNo()));
                        if (whsStorageInventory == null || whsStorageInventory.getQuantity() < qty) {
                            return ResponseResult.error("Storage Inventory check failed for materialNo: " + sapDeliveryNoteDtl.getMaterialNo());
                        }
                    }
                }
            }
            return ResponseResult.success();
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.error("Error when checking storage inventory");
        }
    }

    /* 重置 SAP_DELIVERY_NOTE
     *  SPMS_STATUS 0,
     *  DOCUMENT_DATE,
     *  POSTING_DATE,
     *  MOBILE_TYPE,
     *  USER_ID,
     *  PDA_SN,
     *  SAP_VOUCHER_NUMBER,
     *  SAP_VOUCHER_YEAR
     *  设为空
     *  */
    @Override
    public ResponseResult resetSapDeliveryNote(String deliveryNoteSap) {
        try {
            UpdateWrapper updateWrapper = new UpdateWrapper<SapDeliveryNote>().eq("DELIVERY_NOTE_SAP", deliveryNoteSap);
            SapDeliveryNote sapDeliveryNote = new SapDeliveryNote();
            sapDeliveryNote.setSpmsStatus("0");
            // Aug 3, kpzhang@cn.ibm.com,  近用户要求,在撤销采购入库时,不清空行上的实收数量
//            sapDeliveryNote.setDocumentDate("");
//            sapDeliveryNote.setPostingDate("");
//            sapDeliveryNote.setMobileType("");
//            sapDeliveryNote.setUserId("");
//            sapDeliveryNote.setSapVoucherNumber("");
//            sapDeliveryNote.setSapVoucherYear("");
            sapDeliveryNoteMapper.update(sapDeliveryNote, updateWrapper);
            return ResponseResult.success();
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.error("重置SAP_DELIVERY_NOTE DOCUMENT_DATE,POSTING_DATE,MOBILE_TYPE,USER_ID, PDA_SN,SAP_VOUCHER_NUMBER,SAP_VOUCHER_YEAR设为空存,失败");
        }
    }

    /* 重置 SAP_DELIVERY_NOTE_DTL RECEIVED_QTY,ITEM_STATUS, TEMP_STORAGE */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult resetSapDeliveryNoteDtl(List<SapDeliveryNoteDtl> sapDeliveryNoteDtls, String userId,String werks,String whsLocationCode) {
        try {
            JSONArray objList = new JSONArray();
            for (int i = 0; i < sapDeliveryNoteDtls.size(); i++) {
                // 更新行项目
                String tempStorage = sapDeliveryNoteDtls.get(i).getTempStorage();
                // Aug 3, kpzhang@cn.ibm.com,  近用户要求,在撤销采购入库时,不清空行上的实收数量
//                SapDeliveryNoteDtl sapDeliveryNoteDtl = new SapDeliveryNoteDtl();
//                sapDeliveryNoteDtl.setTempStorage("[]");
//                sapDeliveryNoteDtl.setReceivedQty(0.0);
//                sapDeliveryNoteDtl.setItemStatus("0");
                String deliveryNoteSap = sapDeliveryNoteDtls.get(i).getDeliveryNoteSap();
                String materialNo = sapDeliveryNoteDtls.get(i).getMaterialNo();

                // 扣减储位库存
                JSONArray storageList = JSONArray.parseArray(tempStorage);
                if (storageList != null && storageList.size() > 0){
                    for (int k = 0; k < storageList.size(); k++) {
                        JSONObject storageObj = storageList.getJSONObject(k);
                        String storageUuid = storageObj.getString("storageUuid");
                        Double qty = storageObj.getDouble("qty");

                        // 扣减储位库存
                        if (whsStorageInventoryService.updateWhsStorage(storageUuid, materialNo, qty) < 0) {
                            throw new Exception("Update Storage Inventory failed for " + materialNo + " on storage storageUuid: " +
                                    storageUuid +", qty: " + qty);
                        }
                        iWhsOperateLogService.insertOperateLog(
                                Constans.WhsOperateLog_DocumentType_NanShaStorageLog,
                                storageUuid,
                                materialNo,
                                "",
                                qty,
                                Constans.WhsOperateLog_OperationType_ShelfOff,
                                deliveryNoteSap,
                                Constans.WHS_WhsIn_Withdraw_ShelfOffM,
                                userId,
                                Constans.WHS_WhsIn_WithdrawM,
                                werks,
                                whsLocationCode,
                                deliveryNoteSap);

                        // 将数据返回，用于创建冲销任务明细
                        storageObj.put("materialNo", materialNo);
                        objList.add(storageObj);
                    }
                }
                // Aug 3, kpzhang@cn.ibm.com,  近用户要求,在撤销采购入库时,不清空行上的实收数量
//                int res = sapDeliveryNoteDtlMapper.update(sapDeliveryNoteDtl, new UpdateWrapper<SapDeliveryNoteDtl>()
//                        .eq("DELIVERY_NOTE_SAP", deliveryNoteSap).eq("MATERIAL_NO", materialNo));
//                if (res <= 0) {
//                    throw new Exception("Error when update DeliverNoteDtl + materialNo: " + materialNo + " , deliveryNoteSap: " + deliveryNoteSap);
//                }
            }
            return ResponseResult.success().add("storageList", objList.toArray());
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ResponseResult.error("Error when reset SapDeliveryNoteDtl");
        }
    }


}
